package cn.well.cloud.quartz.core.controller;

import cn.stylefeng.roses.core.util.ToolUtil;
import cn.stylefeng.roses.kernel.model.exception.RequestEmptyException;
import cn.stylefeng.roses.kernel.model.exception.enums.CoreExceptionEnum;
import cn.stylefeng.roses.kernel.model.response.ResponseData;
import cn.well.cloud.base.util.AbstractController;
import cn.well.cloud.quartz.core.model.ScheduleJob;
import cn.well.cloud.quartz.core.task.TaskUtils;
import cn.well.cloud.quartz.modular.model.Timetask;
import com.alibaba.fastjson.JSONObject;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;


/**
 * 定时任务调度API
 * 调用形式：Http
 * Created by wison on 2019年9月10日.
 */
@Component
@RequestMapping(value = "opt")
public class JobController extends AbstractController {

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    @Autowired
    private TaskUtils taskUtils;

    /**
     * 获取所有计划中的任务列表
     * @return
     * @throws SchedulerException
     * @throws IOException
     */
    @RequestMapping(value = "/getAllJob")
    @ResponseBody
    public Object getAllJob() throws SchedulerException, IOException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
        Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
        List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
        for (JobKey jobKey : jobKeys) {
            List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
            for (Trigger trigger : triggers) {
                ScheduleJob job = new ScheduleJob();
                job.setJobId(trigger.getDescription());// description 放的是job的id
                job.setJobName(jobKey.getName());
                job.setJobGroup(jobKey.getGroup());
                job.setDescription("触发器:" + trigger.getKey());
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                job.setJobStatus(triggerState.name());
                if (trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    job.setCronExpression(cronExpression);
                }
                jobList.add(job);
            }
        }
        return ResponseData.success(jobList);
    }

    /**
     * 所有正在运行的job
     * @param request
     * @param response
     * @return
     * @throws SchedulerException
     * @throws IOException
     */
    @RequestMapping(value = "/getRunningJob")
    @ResponseBody
    public Object getRunningJob(HttpServletRequest request, HttpServletResponse response) throws SchedulerException, IOException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
        List<ScheduleJob> jobList = new ArrayList<ScheduleJob>(executingJobs.size());
        for (JobExecutionContext executingJob : executingJobs) {
            ScheduleJob job = new ScheduleJob();
            JobDetail jobDetail = executingJob.getJobDetail();
            JobKey jobKey = jobDetail.getKey();
            Trigger trigger = executingJob.getTrigger();
            job.setJobName(jobKey.getName());
            job.setJobGroup(jobKey.getGroup());
            job.setDescription("触发器:" + trigger.getKey());
            Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
            job.setJobStatus(triggerState.name());
            if (trigger instanceof CronTrigger) {
                CronTrigger cronTrigger = (CronTrigger) trigger;
                String cronExpression = cronTrigger.getCronExpression();
                job.setCronExpression(cronExpression);
            }
            jobList.add(job);
        }
        return ResponseData.success(jobList);
    }

    /**
     *  添加任务
     * @param request
     * @param response
     * @return
     * @throws SchedulerException
     * @throws IOException
     */
    @RequestMapping(value = "/addJob")
    @ResponseBody
    public Object addJob(HttpServletRequest request, HttpServletResponse response) throws SchedulerException, IOException {
        ScheduleJob job = new ScheduleJob();
        JSONObject obj = super.getBodyParam();
        if (ToolUtil.isNotEmpty(obj)) {
            Timetask timetask = JSONObject.toJavaObject(obj, Timetask.class);
            if (timetask != null) {
                job.setJobId(timetask.getTaskId().toString());
                job.setJobGroup(timetask.getGroupName()); // 任务组
                job.setJobName(timetask.getName());// 任务名称
                job.setJobStatus(timetask.getJobStatus()); // 任务发布状态
                job.setIsConcurrent(timetask.getConcurrent().toString()); // 运行状态
                job.setCronExpression(timetask.getCron());
                job.setBeanClass(timetask.getBeanName());// 一个以所给名字注册的bean的实例
                job.setMethodName(timetask.getMethodName());
                job.setJobData(timetask.getJobData()); // 参数
            }
        } else {
            throw new RequestEmptyException(CoreExceptionEnum.IO_ERROR.getMessage());
        }
        taskUtils.addJob(job);
        return ResponseData.success();
    }

    /**
     * 暂停一个job
     * @return
     * @throws SchedulerException
     * @throws IOException
     */
    @RequestMapping(value = "/pauseJob")
    @ResponseBody
    public Object pauseJob() throws SchedulerException, IOException {
        JSONObject obj = super.getBodyParam();
        if (ToolUtil.isNotEmpty(obj)) {
            Timetask timetask = JSONObject.toJavaObject(obj, Timetask.class);
            if (timetask != null) {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                JobKey jobKey = JobKey.jobKey(timetask.getName(), timetask.getGroupName());
                scheduler.pauseJob(jobKey);
            } else {
                throw new RequestEmptyException();
            }
        } else {
            throw new RequestEmptyException(CoreExceptionEnum.IO_ERROR.getMessage());
        }
        return ResponseData.success();

    }

    /**
     * 恢复一个job
     * @param request
     * @param response
     * @return
     * @throws SchedulerException
     * @throws IOException
     */
    @RequestMapping(value = "/resumeJob")
    @ResponseBody
    public Object resumeJob(HttpServletRequest request, HttpServletResponse response) throws SchedulerException, IOException {
        JSONObject obj = super.getBodyParam();
        if (ToolUtil.isNotEmpty(obj)) {
            Timetask timetask = JSONObject.toJavaObject(obj, Timetask.class);
            if (timetask != null) {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                JobKey jobKey = JobKey.jobKey(timetask.getName(), timetask.getGroupName());
                scheduler.resumeJob(jobKey);
            } else {
                throw new RequestEmptyException();
            }
        } else {
            throw new RequestEmptyException(CoreExceptionEnum.IO_ERROR.getMessage());
        }
        return ResponseData.success();
    }

    /**
     * 删除一个job
     * @param request
     * @param response
     * @return
     * @throws SchedulerException
     * @throws IOException
     */
    @RequestMapping(value = "/deleteJob")
    @ResponseBody
    public Object deleteJob(HttpServletRequest request, HttpServletResponse response) throws SchedulerException, IOException {
        JSONObject obj = super.getBodyParam();
        if (ToolUtil.isNotEmpty(obj)) {
            Timetask timetask = JSONObject.toJavaObject(obj, Timetask.class);
            if (timetask != null) {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                JobKey jobKey = JobKey.jobKey(timetask.getName(), timetask.getGroupName());
                scheduler.deleteJob(jobKey);
            } else {
                throw new RequestEmptyException();
            }
        } else {
            throw new RequestEmptyException(CoreExceptionEnum.IO_ERROR.getMessage());
        }
        return ResponseData.success();
    }

    /**
     *  立即执行job
     * @param request
     * @param response
     * @return
     * @throws SchedulerException
     * @throws IOException
     */
    @RequestMapping(value = "/runAJobNow")
    @ResponseBody
    public Object runAJobNow(HttpServletRequest request, HttpServletResponse response) throws SchedulerException, IOException {
        JSONObject obj = super.getBodyParam();
        if (ToolUtil.isNotEmpty(obj)) {
            Timetask timetask = JSONObject.toJavaObject(obj, Timetask.class);
            if (timetask != null) {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                JobKey jobKey = JobKey.jobKey(timetask.getName(), timetask.getGroupName());
                scheduler.triggerJob(jobKey);
            } else {
                throw new RequestEmptyException();
            }
        } else {
            throw new RequestEmptyException(CoreExceptionEnum.IO_ERROR.getMessage());
        }
        return ResponseData.success();
    }

    /**
     * 更新job时间表达式
     * @param request
     * @param response
     * @return
     * @throws SchedulerException
     * @throws IOException
     */
    @RequestMapping(value = "/updateJobCron")
    @ResponseBody
    public Object updateJobCron(HttpServletRequest request, HttpServletResponse response) throws SchedulerException, IOException {
        JSONObject obj = super.getBodyParam();
        if (ToolUtil.isNotEmpty(obj)) {
            Timetask timetask = JSONObject.toJavaObject(obj, Timetask.class);
            if (timetask != null) {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                JobKey jobKey = JobKey.jobKey(timetask.getName(), timetask.getGroupName());

                TriggerKey triggerKey = TriggerKey.triggerKey(timetask.getName(), timetask.getGroupName());

                CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(timetask.getCron());

                trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

                scheduler.rescheduleJob(triggerKey, trigger);
            } else {
                throw new RequestEmptyException();
            }
        } else {
            throw new RequestEmptyException(CoreExceptionEnum.IO_ERROR.getMessage());
        }
        return ResponseData.success();
    }
}
